/* Darren Mui - CS362 */

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"

#define NOISY_TEST 1

int main () {
	int i, r, n, p;
	int deckTreasureBef, discardTreasureBef, handTreasureBef;
	int deckTreasureAft, discardTreasureAft, handTreasureAft;
	int deckCountBef, discardCountBef, handCountBef;
	int deckCountAft, discardCountAft, handCountAft;
	int counterDeck, counterTreasure, counterHandTreasure;

	SelectStream(2);
	PutSeed(3);

	struct gameState G;

	printf ("Testing Adventurer with Random Tests.\n");

	counterDeck = 0;
	counterTreasure = 0;
	counterHandTreasure = 0;

	for (n = 0; n < 100; n++) {
		for (i = 0; i < sizeof(struct gameState); i++) {
			((char*)&G)[i] = floor(Random() * 256);
		}
		deckTreasureBef = 0;
		discardTreasureBef = 0;
		handTreasureBef = 0;
		deckTreasureAft = 0;
		discardTreasureAft = 0;
		handTreasureAft = 0;

		p = floor(Random() * 2); // randomize player from 0 to 1
		G.whoseTurn = p;

		// to make sure that the deck + discard actually have two treasure cards
		while ((deckTreasureBef + discardTreasureBef) < 2) {
			G.deckCount[p] = floor(Random() * MAX_DECK); // randomize # of cards in deck for player p
			//set each card in the player p's deck to a random card from curse to treasure_map (based on the enum in dominion.h)
			for (i = 0; i < G.deckCount[p]; i++) {
				G.deck[p][i] = floor(Random() * treasure_map);
				if (G.deck[p][i] >= copper && G.deck[p][i] <= gold) {
					deckTreasureBef++;
				}
			}

			G.discardCount[p] = floor(Random() * MAX_DECK); // randomize # of cards in discard for player p
			//set each card in the player p's discard to a random card from curse to treasure_map (based on the enum in dominion.h)
			for (i = 0; i < G.discardCount[p]; i++) {
				G.discard[p][i] = floor(Random() * treasure_map);
				if (G.discard[p][i] >= copper && G.discard[p][i] <= gold) {
					discardTreasureBef++;
				}
			}

			if ((deckTreasureBef + discardTreasureBef) < 2) {
				deckTreasureBef = 0;
				discardTreasureBef = 0;
			}
		}

		G.handCount[p] = floor(Random() * MAX_HAND); // randomize # of cards in player p's hand
		//set each card in the player p's hand to a random card from curse to treasure_map (based on the enum in dominion.h)
		for (i = 0; i < G.handCount[p]; i++) {
			G.hand[p][i] = floor(Random() * treasure_map);
			if (G.hand[p][i] >= copper && G.hand[p][i] <= gold) {
				handTreasureBef++;
			}
		}

		deckCountBef = G.deckCount[p];
		discardCountBef = G.discardCount[p];
		handCountBef = G.handCount[p]; 

		#if (NOISY_TEST == 1)
				printf("BEFORE PLAYING ADVENTURER\n");
				printf("   deckCount: %d \t    discardCount: %d  \t    handCount: %d  \t    totalCount: %d\n", deckCountBef, discardCountBef, handCountBef, deckCountBef + discardCountBef + handCountBef);
				printf("deckTreasure: %d \t discardTreasure: %d  \t handTreasure: %d  \t totalTreasure: %d\n", deckTreasureBef, discardTreasureBef, handTreasureBef, deckTreasureBef + discardTreasureBef + handTreasureBef);
		#endif

		r = cardEffect(adventurer, -1, -1, -1, &G, 0, 0); // play Adventurer from handPos 0, even if that card isn't actually an Adventurer card
		assert(r == 0);

		deckCountAft = G.deckCount[p];
		discardCountAft = G.discardCount[p];
		handCountAft = G.handCount[p]; 

		for (i = 0; i < G.deckCount[p]; i++) {
			if (G.deck[p][i] >= copper && G.deck[p][i] <= gold) {
				deckTreasureAft++;
			}
		}
		for (i = 0; i < G.discardCount[p]; i++) {
			if (G.discard[p][i] >= copper && G.discard[p][i] <= gold) {
				discardTreasureAft++;
			}
		}
		for (i = 0; i < G.handCount[p]; i++) {
			if (G.hand[p][i] >= copper && G.hand[p][i] <= gold) {
				handTreasureAft++;
			}
		}

		#if (NOISY_TEST == 1)
				printf("AFTER PLAYING ADVENTURER\n");
				printf("   deckCount: %d \t    discardCount: %d  \t    handCount: %d  \t    totalCount: %d\n", deckCountAft, discardCountAft, handCountAft, deckCountAft + discardCountAft + handCountAft);
				printf("deckTreasure: %d \t discardTreasure: %d  \t handTreasure: %d  \t totalTreasure: %d\n\n", deckTreasureAft, discardTreasureAft, handTreasureAft, deckTreasureAft + discardTreasureAft + handTreasureAft);
		#endif

		// make sure number of cards stay the same after using Adventurer 
		if ((deckCountBef + discardCountBef + handCountBef) != (deckCountAft + discardCountAft + handCountAft)) {
			counterDeck++;
		}
		// make sure number of treasure cards stay the same after using Adventurer
		if ((deckTreasureBef + discardTreasureBef + handTreasureBef) != (deckTreasureAft + discardTreasureAft + handTreasureAft)) {
			counterTreasure++;
		}
		// make sure that the number of treasure cards in each respective piles have properly increased/decreased
		if (handTreasureAft != (handTreasureBef + 2)) {
			if ((deckTreasureBef + discardTreasureBef) != (deckTreasureAft + discardTreasureAft - 2)) {
				counterHandTreasure++;
			}
		}

	}

	printf("TESTS COMPLETE\n");
	printf("%d tests failed\n", counterDeck + counterTreasure + counterHandTreasure);
	printf("%d deck count incorrect\n", counterDeck);
	printf("%d treasure card count incorrect\n", counterTreasure);
	printf("%d treasure card count in card pile incorrect\n", counterHandTreasure);

	return 0;
}
